﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;


namespace DARE
{
    /// <summary>
    /// This class represents a cursor displayed by a HUD System.
    /// The cursor uses CHUDTextures to be draw so you can animate it as you want.
    /// You can register many CHUDTexture with a name as identifier.
    /// The texture displayed is the current texture (Texture property).
    /// To change this current texture, just call SetTexture() with the name of the texture you want.
    /// <code>
    /// CHudTexture tex = new CHudTexture();
    /// tex.AnimationState.SpriteSheet = CResourceMgr.Load<Texture2D>("Textures/LoadingCircle");
    /// tex.AnimationState.AnimationType = CAnimationState.EAnimationType.LOOP;
    /// tex.AnimationState.AnimationInterval = 50;
    /// tex.AnimationState.AddState(new Rectangle(0, 0, 102, 102));
    /// tex.AnimationState.AddState(new Rectangle(102, 0, 102, 102));
    /// tex.AnimationState.AddState(new Rectangle(204, 0, 102, 102));
    /// tex.AnimationState.AddState(new Rectangle(306, 0, 102, 102));
    /// tex.AnimationState.AddState(new Rectangle(408, 0, 102, 102));
    /// tex.AnimationState.AddState(new Rectangle(510, 0, 102, 102));
    /// tex.AnimationState.AddState(new Rectangle(612, 0, 102, 102));
    /// tex.AnimationState.AddState(new Rectangle(714, 0, 102, 102));
    /// tex.AnimationState.Start();
    /// m_hud.Cursor.Textures.Add("loading", tex);
    /// </code>
    /// <code>
    /// if (isLoading)
    ///     m_hud.Cursor.SetTexture("loading");
    /// else
    ///     m_hud.Cursor.SetDefaultTexture();
    /// </code>
    /// </summary>
    [AttrTypeDependentSerializable(typeof(CCursorData))]
    public class CCursor
    {
        #region fields

        private CHudTexture m_currentTexture;
        private Dictionary<string, CHudTexture> m_textures;
        private SpriteBatch m_spriteBatch;
        private CHUDSystem m_hud;
        private Vector2 m_size;
        private Rectangle m_intersectionRect;
        private CWidget m_widgetUnder;

        #endregion

        #region properties

        public bool IsVisible { get; set; }

        /// <summary>
        /// Gets/Sets the current cursor texture
        /// </summary>
        public CHudTexture Texture { get { return m_currentTexture; } set { m_currentTexture = value; if (m_currentTexture == null)return; m_currentTexture.Rectangle = new Rectangle(m_currentTexture.Rectangle.X, m_currentTexture.Rectangle.Y, (int)m_size.X, (int)m_size.Y); } }

        /// <summary>
        /// Gets/Sets the dictionary of textures.
        /// The string represents the identifier of the texture to be set by SetTexture method.
        /// </summary>
        /// <seealso cref="SetTexture"/>
        public Dictionary<string, CHudTexture> Textures { get { return m_textures; } set { m_textures = value; } }

        /// <summary>
        /// Gets/Sets the rectangle of the current texture
        /// </summary>
        public Rectangle Rectangle { get { return m_currentTexture.Rectangle; } set { m_currentTexture.Rectangle = value; } }

        /// <summary>
        /// Gets/Sets the SpriteBatch used by this CCursor
        /// </summary>
        public SpriteBatch SpriteBatch { get { return m_spriteBatch; } set { m_spriteBatch = value; } }

        /// <summary>
        /// Gets/Sets the CHUDSystem containing this CCursor
        /// </summary>
        public CHUDSystem HUD { get { return m_hud; } set { m_hud = value; m_spriteBatch = m_hud.SpriteBatch; } }

        /// <summary>
        /// Gets/Sets the size of the cursor
        /// </summary>
        public Vector2 Size { get { return m_size; } set { m_size = value; m_currentTexture.Rectangle = new Rectangle(m_currentTexture.Rectangle.X, m_currentTexture.Rectangle.Y, (int)m_size.X, (int)m_size.Y); } }

        /// <summary>
        /// Gets the intersection rectangle
        /// </summary>
        public Rectangle IntersectionRect { get { return m_intersectionRect; } }

        #endregion

        #region ctor

        public CCursor(CHUDSystem hud)
        {
            HUD = hud;
            m_spriteBatch = HUD.SpriteBatch;
            m_textures = HUD.Skinner.GetCursorTextures();
            m_currentTexture = m_textures.First().Value;
            m_size = new Vector2(20, 20);
            Vector2 mpos = CDare.Instance.InputMgr.Mouse.Position;
            m_currentTexture.Rectangle = new Rectangle((int)mpos.X, (int)mpos.Y, (int)m_size.X, (int)m_size.Y);
            m_intersectionRect = new Rectangle((int)mpos.X - 2, (int)mpos.Y - 2, 10, 10);
            IsVisible = true;
        }

        #endregion

        #region methods

        /// <summary>
        /// Sets the default texture as current texture.
        /// </summary>
        public void SetDefaultTexture()
        {
            m_currentTexture = m_textures.First().Value;
            Vector2 mpos = CDare.Instance.InputMgr.Mouse.Position;
            m_currentTexture.Rectangle = new Rectangle((int)mpos.X, (int)mpos.Y, (int)m_size.X, (int)m_size.Y);
            m_intersectionRect = new Rectangle((int)mpos.X - 2, (int)mpos.Y - 2, 10, 10);
        }

        /// <summary>
        /// Sets the texture identified by the given name as current texture if a texture was registered with this name.
        /// If there isn't any texture registered with this name, nothing is done.
        /// </summary>
        public void SetTexture(string name)
        {
            if (m_textures.ContainsKey(name))
            {
                m_currentTexture = m_textures[name];
                Vector2 mpos = CDare.Instance.InputMgr.Mouse.Position;
                m_size = new Vector2(m_currentTexture.Body.Width, m_currentTexture.Body.Height);
                m_currentTexture.Rectangle = new Rectangle((int)mpos.X, (int)mpos.Y, (int)m_size.X, (int)m_size.Y);
                m_intersectionRect = new Rectangle((int)mpos.X - 2, (int)mpos.Y - 2, 10, 10);
            }
        }

        /// <summary>
        /// Registers a texture with an identifier.
        /// </summary>
        /// <param name="name">texture identifier</param>
        /// <param name="texture">texture</param>
        /// <param name="overrideTexture">if this value is set to true and if there is already a texture registered with the given name, the new texture will override the old one</param>
        /// <seealso cref="SetTexture"/>
        public CCursor RegisterTexture(string name, CHudTexture texture, bool overrideTexture)
        {
            if (!m_textures.ContainsKey(name))
                m_textures.Add(name, texture);
            else if (overrideTexture)
                m_textures[name] = texture;
            return this;
        }

        public CCursor RegisterTexture(string name, CHudTexture texture)
        {
            return RegisterTexture(name, texture, false);
        }

        /// <summary>
        /// Unregisters a texture
        /// </summary>
        /// <returns></returns>
        public CCursor UnregisterTexture(string name)
        {
            m_textures.Remove(name);
            return this;
        }

        public void Update(GameTime gameTime)
        {
            if (m_currentTexture == null)
                return;
            Vector2 mpos = CDare.Instance.InputMgr.Mouse.Position;
            if (m_currentTexture.Rectangle.X != (int)mpos.X || m_currentTexture.Rectangle.Y != (int)mpos.Y)
                m_currentTexture.Rectangle = new Rectangle((int)(mpos.X * DARE.CDare.Instance.Config.Video.WindowRatio.X), (int)(mpos.Y * DARE.CDare.Instance.Config.Video.WindowRatio.Y), (int)m_size.X, (int)m_size.Y);
            m_intersectionRect = new Rectangle((int)((mpos.X - 2)* DARE.CDare.Instance.Config.Video.WindowRatio.X), (int)((mpos.Y - 2) * DARE.CDare.Instance.Config.Video.WindowRatio.Y), 5, 5);
        }

        public void Draw(GameTime gameTime)
        {
            if (IsVisible && m_currentTexture != null)
                m_currentTexture.Draw(gameTime);
        }

        #endregion

    }
}
